/**
 * 
 */
package ae.pcfc.cldos.online.web.controller.client.company.nocandletters;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.MappingJsonFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.soap.client.SoapFaultClientException;

import ae.pcfc.cldos.online.common.ConstantsCommon;
import ae.pcfc.cldos.online.common.delegate.NocLetterDelegate;
import ae.pcfc.cldos.online.common.exception.GSAppException;
import ae.pcfc.cldos.online.common.exception.InvalidEmpIdException;
import ae.pcfc.cldos.online.common.exception.LeaseExpireException;
import ae.pcfc.cldos.online.common.exception.LicenseErrorRemarkException;
import ae.pcfc.cldos.online.common.exception.LicenseExpiredException;
import ae.pcfc.cldos.online.common.exception.PaymentException;
import ae.pcfc.cldos.online.common.exception.UltimusAppException;
import ae.pcfc.cldos.online.common.vo.AppSaveResponseVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.app.comments.ApplicationCommentVO;
import ae.pcfc.cldos.online.common.vo.nandl.NocLetterDetailsVO;
import ae.pcfc.cldos.online.common.vo.nandl.NocLetterVO;
import ae.pcfc.cldos.online.web.Constants;
import ae.pcfc.cldos.online.web.PageType;
import ae.pcfc.cldos.online.web.ViewPath;
import ae.pcfc.cldos.online.web.ViewUtils;
import ae.pcfc.cldos.online.web.model.NocAndLettersModel;
import ae.pcfc.cldos.online.web.services.breadcrumbs.BreadCrumbsFactoryService;


/**
 * 
 * @author Sergey Manoylo
 *
 */
@Controller
@RequestMapping(ViewPath.__NOC_LETTERS_SUBMITION)
public class NocAndLettersSubmitionController extends NocAndLettersCommonController {
	
	private static final String NOC_AND_LETTERS_PATH = "client.company.nocandletters.submition.form";
	
	private static final String NOC_AND_LETTERS_MODEL = "nocAndLettersModel";
	
	
	@Autowired
	private NocLetterDelegate nocLetterDelegate;

	
	@RequestMapping(method=RequestMethod.GET, value="/form.htm")
	public ModelAndView form(
			ModelMap model,			
			@ModelAttribute(value="nocAndLettersModel") NocAndLettersModel nocAndLettersModel){
		
		return new ModelAndView(NOC_AND_LETTERS_PATH,model);
	}
	
	@RequestMapping(method=RequestMethod.GET, value="/resubmitForm.htm")
	public ModelAndView resubmitForm(
			@RequestParam String appId,
			ModelMap model,
			@ModelAttribute(value=NOC_AND_LETTERS_MODEL) NocAndLettersModel nocAndLettersModel) throws Exception{
		
		populateResubmitInfo(appId, nocAndLettersModel, model);
		
		return new ModelAndView(NOC_AND_LETTERS_PATH,model);
	}
	
	@ModelAttribute
	public void populateMappingsInJson(ModelMap model) throws JsonGenerationException, JsonMappingException, IOException {
		MappingJsonFactory jsonFactory = new MappingJsonFactory();
		{
			StringWriter sw = new StringWriter(); // serialize
			ObjectMapper mapper = new ObjectMapper();
			JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
			mapper.writeValue(jsonGenerator, NocAndLettersConstants.NOC_FIELDS_MAPPING);
			sw.close();
			model.put(Constants.__NOC_LETTERS_NOC_FIELDS_MAPPING_JSON_MODEL, sw.toString());
		}
		{
			StringWriter sw = new StringWriter(); // serialize
			ObjectMapper mapper = new ObjectMapper();
			JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
			mapper.writeValue(jsonGenerator, NocAndLettersConstants.LANG_NOC_MAPPING);
			sw.close();
			model.put(Constants.__NOC_LETTERS_NOC_LANG_MAPPING_JSON_MODEL, sw.toString());
		}
	}
	
	@ModelAttribute
	public void populateBreadCrumbs(ModelMap model, @RequestParam(required=false) String appId) {
		if(appId==null){ //if submit new
			breadCrumbsFactoryService.populateNocAndLettersBreadcrumb(model);
		} else { //for resubmition
			breadCrumbsFactoryService.populateNocAndLettersTasktBreadcrumb(model, appId, BreadCrumbsFactoryService.TASK_TYPE_RESUBMIT);
		}
	}
	
	private void populateResubmitInfo(String appId,  NocAndLettersModel nocAndLettersModel, ModelMap model) throws NumberFormatException, Exception{

		UserVO userVO = getUserVO();	
		
		NocLetterVO nocLetterVO = nocLetterDelegate.getNocLetterAppInfo(encryptionDelegate.decodeAndDecrypt(appId), userVO, ConstantsCommon.Steps.RESUBMIT);
		getMapper().map(nocLetterVO.getNocLetterDetailsVO(),nocAndLettersModel);
		
		model.put("isResubmit", true);
		model.put("appId", appId);
		model.put("comments", nocLetterVO.getApplicationCommentVOs());
		model.put("submitUri", ViewPath.__NOC_LETTERS_SUBMITION+"/resubmitForm.htm?appId="+appId);
	}
	
	@RequestMapping(method=RequestMethod.POST, value={"/form.htm", "/resubmitForm.htm"})
	public ModelAndView submit(
			HttpServletRequest request,
			ModelMap model,
			@RequestParam(required=false, defaultValue="false") boolean isResubmit,
			@RequestParam(required=false) String fnpServiceCode,	
			@RequestParam(required=false) String formId,
			@RequestParam(required=false) String appId,
			@ModelAttribute(value="nocAndLettersModel") @Valid NocAndLettersModel nocAndLettersModel,
			BindingResult errors
			) throws Exception {

		ModelAndView mav = null;
		
		if(isResubmit)  {
			boolean isClose = WebUtils.hasSubmitParameter(request, "CloseBtn");
			if(isClose) {
				return new ModelAndView(ViewUtils.getRedirect(ViewPath.__ADMIN_TASKS, PageType.SHOW));
			}
		}
		
		NocLetterVO nocLetterVO = new NocLetterVO();
		NocLetterDetailsVO nocLetterDetailsVO = new NocLetterDetailsVO();
		getMapper().map(nocAndLettersModel,nocLetterDetailsVO);
		
		if(securityService.isCompanyAdmin() && (fnpServiceCode==null || fnpServiceCode.isEmpty())){
			errors.reject("no.payment.code");
		} else if(securityService.isCompanyAdmin()){
			processFnp(request,fnpServiceCode,errors, nocLetterVO.getFnpParamsVO());			
		}			
		
		AppSaveResponseVO appSaveResponseVO = null;
		
		if (!errors.hasErrors()) {
			
			nocLetterVO.setNocLetterDetailsVO(nocLetterDetailsVO);
			nocLetterVO.setUserVO(getUserVO());
			nocLetterVO.setFnpServiceCode(fnpServiceCode);
			
			ApplicationCommentVO applicationCommentVO = new ApplicationCommentVO();
			
			applicationCommentVO.setUsername(securityService.getLoginedUsername());
			applicationCommentVO.setDate(new Date());
			applicationCommentVO.setComment(nocAndLettersModel.getAdminComments());
			
			nocLetterVO.setApplicationCommentVO(applicationCommentVO);
			try{
				if(isResubmit) {
					appSaveResponseVO = nocLetterDelegate.reSubmit(nocLetterVO, encryptionDelegate.decodeAndDecrypt(appId));
				} else {
					appSaveResponseVO = nocLetterDelegate.submit(nocLetterVO);	
				}
			} catch (PaymentException e) {
				errors.reject("error.payment");
			} catch (LeaseExpireException e){
				errors.reject("lease.expire");
			} catch (LicenseExpiredException e) {
				errors.reject("license.expire");
			}catch (LicenseErrorRemarkException e) {
				errors.reject("license.errorremark");
			}catch(InvalidEmpIdException e){
				errors.reject("invalid.employee");
			}catch(GSAppException e){
				errors.reject("unable.to.proceed.gs.down");
			}catch(UltimusAppException e){
				errors.reject("unable.to.proceed.ultimus.down");
			}catch(WebServiceIOException e){
				e.printStackTrace();
				errors.reject("unable.to.proceed.gs.fnp.down");
			}catch(SoapFaultClientException e){
				e.printStackTrace();
				errors.reject("unable.to.proceed.gs.fnp.down");
			}catch(Exception e){
				e.printStackTrace();
				errors.reject("unable.to.proceed");
			}
		}
		
		if(!errors.hasErrors()){
			Map<String, String> paramMap = new HashMap<String, String>();
			paramMap.put(Constants.__REFRENCE_NO, appSaveResponseVO.getReferenceNo());
			if(appSaveResponseVO.getIncidentNo()!=null){
				paramMap.put(Constants.__INCIDENT_NO, appSaveResponseVO.getIncidentNo());
			}
			mav = new ModelAndView(ViewUtils.getRedirect(ViewPath.__CONFIRMATION, PageType.SHOW, paramMap));			
		}else{
			mav =  new ModelAndView(NOC_AND_LETTERS_PATH);
		}
		
		if(errors.hasErrors()){
			if(isResubmit){
				populateResubmitInfo(appId,nocAndLettersModel,model);
			} else{
				model.put("submitUri", ViewPath.__NOC_LETTERS_SUBMITION+"/form.htm");
			}
		}
		return mav;
	}

}
